
```js 
/**  改用class类写 */
class DeepClone {
    constructor(){
        cloneVal: null;
    }
    clone(val, map = new WeakMap()) {
        let type = this.getType(val); //当是引用类型的时候先拿到其确定的类型
        if (this.isObj(val)) {
            switch (type) {
                case 'date':             //日期类型重新new一次传入之前的值，date实例化本身结果不变
                    return new Date(val);
                    break;
                case 'regexp':           //正则类型直接new一个新的正则传入source和flags即可
                    return new RegExp(val.source, val.flags);
                    break;
                case 'function':        //如果是函数类型就直接通过function包裹返回一个新的函数，并且改变this指向
                    return new RegExp(val.source, val.flags);
                    break;
                default:
                    this.cloneVal = Array.isArray(val) ? [] : {};
                    if (map.has(val)) return map.get(val)
                    map.set(val, this.cloneVal)
                    for (let key in val) {
                        if (val.hasOwnProperty(key)) { //判断是不是自身的key
                            this.cloneVal[key] = new DeepClone().clone(val[key], map);
                        }
                    }
                    return this.cloneVal;
            }
        } else {
            return val;     //当是基本数据类型的时候直接返回
        }
    }
    /** 判断是否是引用类型 */
    isObj(val) {   
        return (typeof val == 'object' || typeof val == 'function') && val != null
    }
    /** 获取类型 */
    getType(data) { 
        var s = Object.prototype.toString.call(data);
        return s.match(/\[object (.*?)\]/)[1].toLowerCase();
    };
}
 /** 测试 */
var a ={
    a:1,
    b:true,
    c:undefined,
    d:null,
    e:function(a,b){
        return a + b
    },
    f: /\W+/gi,
    time: new Date(),

}
const deepClone = new DeepClone()
let b = deepClone.clone(a)
console.log(b)
```

:::tip 
Object.assign 是浅拷贝
:::